﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yitter.IdGenerator;

namespace iWare.Wms.Application.PDA
{
    /// <summary>
    /// 呼叫空托服务
    /// </summary>
    [Route("api/EmptyBracket")]
    [ApiDescriptionSettings("PDA", Name = "EmptyBracket", Order = 1)]

    public class EmptyBracketService : IDynamicApiController, ITransient
    {
        private readonly IRepository<WareContainer, MasterDbContextLocator> _wareContainerRep; //容器仓储
        private readonly IRepository<WareLocation, MasterDbContextLocator> _wareLocationRep; //库位仓储
        private readonly IRepository<WareTask, MasterDbContextLocator> _wareTaskRep; //任务仓储
        private readonly IRepository<WareStock, MasterDbContextLocator> _wareStockRep; //库存仓储
        private readonly IRepository<WareLocationVsContainer, MasterDbContextLocator> _wareLocationVsContainerRep; //库位与容器关系仓储

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="wareAccessMouthRep"></param>
        /// <param name="wareContainerRep"></param>
        /// <param name="wareLocationRep"></param>
        /// <param name="wareTaskRep"></param>
        /// <param name="wareStockRep"></param>
        /// <param name="wareLocationVsContainerRep"></param>
        public EmptyBracketService(
             IRepository<WareContainer, MasterDbContextLocator> wareContainerRep,
             IRepository<WareLocation, MasterDbContextLocator> wareLocationRep,
             IRepository<WareTask, MasterDbContextLocator> wareTaskRep,
             IRepository<WareStock, MasterDbContextLocator> wareStockRep,
             IRepository<WareLocationVsContainer, MasterDbContextLocator> wareLocationVsContainerRep
        )
        {
            _wareContainerRep = wareContainerRep;
            _wareLocationRep = wareLocationRep;
            _wareTaskRep = wareTaskRep;
            _wareStockRep = wareStockRep;
            _wareLocationVsContainerRep = wareLocationVsContainerRep;
        }
        #endregion


        /// <summary>
        /// 自动呼叫空托
        /// </summary>
        /// <returns></returns>
        [HttpPost("AutomaticCallEmptyBracket")]
        public async Task AutomaticCallEmptyBracket([FromBody] AutomaticEmptyBracketInput input)
        {
            if (string.IsNullOrEmpty(input.Type)) throw Oops.Oh("容器类型不能为空");
            if (string.IsNullOrEmpty(input.Entrance)) throw Oops.Oh("库口不能为空");

            // 根据容器类型查询库位与容器关系表，状态是正常并且是空托
            var locationVsContainerList = await _wareLocationVsContainerRep.DetachedEntities.Where(z => z.WareContainer.Parameter1 == input.Type
            && z.WareLocation.IsEmptyContainer == YesOrNot.Y && z.WareLocation.AreaID == input.AreaID
            && z.LocationVsContainerStatus == CommonStatus.ENABLE && z.WareLocation.LocationStatus == LocationStatusEnum.cunhuo).ToListAsync();
            if (locationVsContainerList.Count == 0) throw Oops.Oh("库存不足不能呼叫");

            var quantity = new decimal(0.00);
            foreach (var itemStock in locationVsContainerList)
            {
                // 查询库存
                var stockModel = await _wareStockRep.FirstOrDefaultAsync(z => z.ContainerCode == itemStock.ContainerCode);
                quantity += stockModel.CurrentQuantity;

                // 已满足出库的所有数量
                if (quantity > input.Quantity) break;

                // 判断任务
                var taskModel = await _wareTaskRep.FirstOrDefaultAsync(p => p.ContainerCode == itemStock.ContainerCode
                && p.FromLocationCode == itemStock.LocationCode && p.TaskStatus != TaskStatusEnum.Complete);
                if (taskModel != null) continue;

                // 更新库存
                if (stockModel.CurrentQuantity >= input.Quantity) stockModel.CurrentQuantity -= stockModel.CurrentQuantity;
                else stockModel.CurrentQuantity = 0;

                // 新增任务
                taskModel = new WareTask()
                {
                    OrderNo = "N/A",
                    TaskModel = TaskModel.ZIDONG,
                    TaskType = TaskType.Out,
                    TaskNo = YitIdHelper.NextId().ToString(),
                    TaskName = TaskNameConst.CallKongTuo_AutomaticOut,
                    TaskStatus = TaskStatusEnum.NotProgress,
                    Priority = 1,
                    ContainerCode = itemStock.ContainerCode,
                    FromLocationCode = itemStock.LocationCode,
                    ToLocationCode = input.Entrance
                };
                await _wareTaskRep.InsertAsync(taskModel);

                //更新库位
                var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.Code == itemStock.LocationCode && p.LocationStatus == LocationStatusEnum.cunhuo);
                locationModel.LocationStatus = LocationStatusEnum.daichu;
                await _wareLocationRep.UpdateAsync(locationModel);

                //更新关系表
                var wareLocationVsContainer = locationVsContainerList.FirstOrDefault(
                   n => n.ContainerCode == itemStock.ContainerCode && n.LocationCode == itemStock.LocationCode);
                wareLocationVsContainer.LocationVsContainerStatus = CommonStatus.DISABLE;
                await _wareLocationVsContainerRep.UpdateAsync(wareLocationVsContainer);
            }
        }

        /// <summary>
        /// 手动呼叫空托----暂时弃用，后面用的话再放开
        /// </summary>
        /// <returns></returns>
        [HttpPost("ManualCallEmptyBracket")]
        [NonAction]
        public async Task ManualCallEmptyBracket([FromBody] ManualEmptyBracketInput input)
        {
            if (string.IsNullOrEmpty(input.Type)) throw Oops.Oh("容器类型不能为空");
            if (string.IsNullOrEmpty(input.LocationCode)) throw Oops.Oh("库位不能为空");

            // 根据容器类型查询库位与容器关系表，状态是正常并且是空托
            var locationVsContainerList = await _wareLocationVsContainerRep.DetachedEntities.Where(z => z.WareContainer.Parameter1 == input.Type
            && z.WareLocation.IsEmptyContainer == YesOrNot.Y && z.WareLocation.Code == input.LocationCode
            && z.LocationVsContainerStatus == CommonStatus.ENABLE && z.WareLocation.LocationStatus == LocationStatusEnum.cunhuo).ToListAsync();
            if (locationVsContainerList.Count == 0) throw Oops.Oh("无库存不能呼叫");

            // 查询库存
            var stockList = await _wareStockRep.DetachedEntities.Where(z => locationVsContainerList.Select(t => t.ContainerCode).Contains(z.ContainerCode)).ToListAsync();
            //if (stockList.Sum(t => t.CurrentQuantity) == new decimal(0.00)) throw Oops.Oh("库存不足不能呼叫");

            foreach (var itemStock in stockList)
            {
                //检查托盘
                var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(n => n.Code == itemStock.ContainerCode && n.ContainerStatus == ContainerStatusEnum.kuwei);
                if (wareContainer == null) continue; //throw Oops.Oh("托盘不存在！");

                //判断任务
                var taskModel = await _wareTaskRep.FirstOrDefaultAsync(p => p.ContainerCode == itemStock.ContainerCode
                && p.FromLocationCode == itemStock.LocationCode && p.TaskStatus != TaskStatusEnum.Complete);
                if (taskModel != null) continue;

                //查询库存
                var stockModel = await _wareStockRep.FirstOrDefaultAsync(z => z.ContainerCode == itemStock.ContainerCode);
                if (stockModel.CurrentQuantity == new decimal(0.00)) continue; //throw Oops.Oh("库存不足不能呼叫");

                //检查库位
                var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.Code == itemStock.LocationCode && p.LocationStatus == LocationStatusEnum.cunhuo);
                //if (wareContainer == null) throw Oops.Oh("库位不存在！");

                //检查库位与容器关系
                var wareLocationVsContainer = await _wareLocationVsContainerRep.FirstOrDefaultAsync(
                    n => n.ContainerCode == itemStock.ContainerCode && n.LocationCode == itemStock.LocationCode && n.LocationVsContainerStatus == CommonStatus.ENABLE);
                //if (wareLocationVsContainer == null) throw Oops.Oh("托盘库位关系不存在！");

                // 更新库存
                if (stockModel.CurrentQuantity >= input.Quantity)
                {
                    stockModel.CurrentQuantity -= stockModel.CurrentQuantity;
                    // 没有分拣信息的话，这里直接减库存
                    stockModel.StockQuantity -= stockModel.StockQuantity;
                }
                else
                {
                    stockModel.CurrentQuantity = 0;
                    // 没有分拣信息的话，这里直接减库存
                    stockModel.StockQuantity = 0;
                }
                await _wareStockRep.UpdateAsync(stockModel);

                //新增任务
                taskModel = new WareTask()
                {
                    OrderNo = "N/A",
                    TaskModel = TaskModel.SHOUDONG,
                    TaskType = TaskType.Out,
                    TaskNo = YitIdHelper.NextId().ToString(),
                    TaskName = TaskNameConst.CallKongTuo_ManualOut,
                    TaskStatus = TaskStatusEnum.Complete,
                    Priority = 1,
                    ContainerCode = itemStock.ContainerCode,
                    FromLocationCode = itemStock.LocationCode,
                    ToLocationCode = "N/A",
                    UpdatedUserId = CurrentUserInfo.UserId,
                    UpdatedUserName = CurrentUserInfo.Name,
                    UpdatedTime = DateTimeOffset.Now
                };
                await _wareTaskRep.InsertAsync(taskModel);

                //更新库位
                locationModel.LocationStatus = LocationStatusEnum.kongxian;
                locationModel.IsEmptyContainer = YesOrNot.N;
                await _wareLocationRep.UpdateAsync(locationModel);

                //更新关系表
                wareLocationVsContainer.LocationVsContainerStatus = CommonStatus.DELETED;
                await _wareLocationVsContainerRep.UpdateAsync(wareLocationVsContainer);

                //更新托盘状态  【呼叫空托是不是不需要生成分拣信息】
                wareContainer.ContainerStatus = ContainerStatusEnum.kongxian;
                await _wareContainerRep.UpdateAsync(wareContainer);
            }
        }
    }
}
